/**
 * 
 */
package jmine.tec.report.impl;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jmine.tec.report.ExecutableDataColumn;
import jmine.tec.report.ExecutableDataColumnContainer;
import jmine.tec.report.ExecutableDataRow;

/**
 * Class to "curry" a data column, fixing some parameters on construction. The parameters might be changed later.
 * 
 * @author takeshi
 * @version 24/08/2007
 */
public final class CurriedExecutableDataColumn extends SimpleCurriedDataColumn implements Serializable, ExecutableDataColumn {

    private static final long serialVersionUID = -1971271241857402433L;

    private final ExecutableDataColumn delegate;

    /**
     * C'tor
     * 
     * @param delegate the column to curry
     */
    public CurriedExecutableDataColumn(final ExecutableDataColumn delegate) {
        this(delegate, new HashMap<String, Object>());
    }

    /**
     * C'tor
     * 
     * @param delegate the column to curry
     * @param fixedParameters the fixed parameters
     */
    public CurriedExecutableDataColumn(final ExecutableDataColumn delegate, final Map<String, Object> fixedParameters) {
        super(delegate, fixedParameters);
        this.delegate = delegate;
    }

    /**
     * @param obj the other object to compare to
     * @return boolean
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (this.getClass() != obj.getClass()) {
            return false;
        }
        final CurriedExecutableDataColumn other = (CurriedExecutableDataColumn) obj;
        if (this.delegate == null) {
            if (other.delegate != null) {
                return false;
            }
        } else if (!this.delegate.equals(other.delegate)) {
            return false;
        }
        if (this.getFixedParameters() == null) {
            if (other.getFixedParameters() != null) {
                return false;
            }
        } else if (!this.getFixedParameters().equals(other.getFixedParameters())) {
            return false;
        }
        return true;
    }

    /**
     * Executes the rows with the given parameters merged with this {@link CurriedExecutableDataColumn} fixed parameters.
     * 
     * @param rows the rows to execute
     * @param params the parameters from the users
     * @see br.com.maps.util.report.ExecutableDataColumn#execute(java.util.List, java.util.Map)
     */
    public void execute(final List<? extends ExecutableDataRow> rows, final Map<String, Object> params) {
        this.delegate.execute(rows, this.mergeParameters(params));
    }

    /**
     * Executes the rows with the given parameters merged with this {@link CurriedExecutableDataColumn} fixed parameters.
     * 
     * @param type the type of the object
     * @param row the row
     * @param params the {@link Map}
     * @see br.com.maps.util.report.ExecutableDataColumn#executeByObjectType(java.lang.Class, br.com.maps.util.report.ExecutableDataRow,
     * java.util.Map)
     */
    public void executeByObjectType(final Class<?> type, final ExecutableDataRow row, final Map<String, Object> params) {
        this.delegate.executeByObjectType(type, row, this.mergeParameters(params));
    }

    /**
     * @return int
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((this.delegate == null) ? 0 : this.delegate.hashCode());
        result = prime * result + ((this.getFixedParameters() == null) ? 0 : this.getFixedParameters().hashCode());
        return result;
    }

    /**
     * @param type the type
     * @return boolean
     * @see br.com.maps.util.report.ExecutableDataColumn#reactsTo(java.lang.Class)
     */
    public boolean reactsTo(final Class<?> type) {
        return this.delegate.reactsTo(type);
    }

    /**
     * @param container the container
     * @return this
     */
    @Override
    public List<ExecutableDataColumn> buildColumns(final ExecutableDataColumnContainer container) {
        return Collections.singletonList((ExecutableDataColumn) this);
    }
}
